<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<!-- <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> -->
		事件委托演示
		<hr >
		<div id="wrap">
			<div class="wrapitem">1</div>
			<div class="wrapitem">2</div>
			<div class="wrapitem">3</div>
			<div class="wrapitem">4</div>
			<div class="wrapitem">5</div>
			<div class="wrapitem">6</div>
		</div>
		<input type="text" id="ins" value="0">
		<script type="text/javascript">
			/*
				-----------ctrl+f导航api
				将没有层级的变为有层级的，
				两数求和算法，
				柯里化实现add(1)(2)(3),add(1,2)(3)等，
				将数组里面的0移到末尾，
				打印对称数
				旋转数组,
				获取选取的文本，
				复制文本，
				让a==1&&a==2成立，
				请求的四部曲，
				滚动方向判断，
				封装hook调用内容，
				闭包，
				关闭页面前弹出确认，
				事件委托，
				面向组合，
				图片懒加载，
				解析url参数，
				es5构造函数，
				es6构造函数，
				es6的async-await以及promise和promise.all
			*/

			/*将没有层级的变为有层级的=========================================*/
			// let list =[
			// 	{id:1,name:'部门A',parentId:0},
			// 	{id:2,name:'部门B',parentId:0},
			// 	{id:3,name:'部门C',parentId:1},
			// 	{id:4,name:'部门D',parentId:1},
			// 	{id:5,name:'部门E',parentId:2},
			// 	{id:6,name:'部门F',parentId:3},
			// 	{id:7,name:'部门G',parentId:2},
			// 	{id:8,name:'部门H',parentId:4}
			// ];
			// function convert(source, parentId = 0){
			// 	let trees = [];
			// 	for (let i=0;i<source.length;i++) {
			//		let item = source[i]
			// 		if(item.parentId === parentId) {
			// 			let children = convert(source, item['id']);
			// 			if(children.length) {
			// 				item.children = children
			// 			}
			// 			trees.push(item);
			// 		}
			// 	}
			// 	return trees;
			// }
			
			/*两数求和算法(返回相加之后与target相等的两个下标)=========================================*/
			// function anwser (arr, target) {
			// 	let map = {}
			// 	for (let i = 0; i < arr.length; i++) {
			// 		map[arr[i]] = i
			// 	}
			// 	for (let i = 0; i < arr.length; i++) {
			// 		var d = target - arr[i]
			// 		if (map[d]) {
			// 		return [i, map[d]]
			// 		}
			// 	}
			// 	return []
			// }

			/*柯里化实现add(1)(2)(3),add(1,2)(3)等================*/
			// function add(...arg) {
			// 	let res = 0;
			// 	function fn(...arg) {
			// 		res += arg.reduce((total, v) => total + v, 0);
			// 		return fn;
			// 	}
			// 	fn.toString = function () {
			// 		return res
			// 	}
			// 	return fn(...arg)
			// }

			// console.log(add(1))
			// console.log(add(1)(2))
			// console.log(add(1)(2)(3))
			// console.log(add(1, 2)(3))
			// console.log(add(1, 2, 3))

			/*将数组里面的0移到末尾===================================*/
			// function moveZero(arr) {
			// 	let num = 0
			// 	let index = -1
			// 	while ((index = arr.indexOf(0)) > -1) {
			// 		num++
			// 		arr.splice(index, 1)
			// 	}

			// 	while (num--) {
			// 		arr.push(0)
			// 	}
			// }

			/*打印对称数========================================*/
			// var result = [];
			// for (let i = 1; i <= 10000; i++) {
			// 	let origin = '' + i;
			// 	let reverse = origin.split('').reverse().join('');
			// 	if(origin === reverse) {
			// 		result.push(i);
			// 	}
			// }

			/*旋转数组=========================================*/
			// function rotate(arr, k) {
			// 	const len = arr.length
			// 	const step = k % len
			// 	return arr.slice(-step).concat(arr.slice(0, len - step))
			// }
			// rotate([1, 2, 3, 4, 5, 6], 7) => [6, 1, 2, 3, 4, 5]

			/*获取选取的文本=================================*/
			// var userSelection, text;
			// if (window.getSelection) {
			// 	//现代浏览器
			// 	userSelection = window.getSelection();
			// } else if (document.selection) {
			// 	//IE浏览器 考虑到Opera，应该放在后面
			// 	userSelection = document.selection.createRange();
			// }
			// if (!(text = userSelection.text)) {
			// 	text = userSelection;
			// }

			/*复制文本=====================================*/
			function copyText(dom,inputid) {
				var text = dom.innerText;
				var input = document.getElementById(inputid);
				input.value = text; // 修改文本框的内容
				input.select(); // 选中文本
				document.execCommand("copy"); // 执行浏览器复制命令
			}
			
			//让a==1&&a==2成立==========================
			/* var a = {
			  value: 0,
			  //三个存在或者随便存在一个，都可以对象转原始类型，也就是基本类型，没有，会报错
			  valueOf: function() {//存在则次级优先调用
			    this.value++;
			    return this.value;
			  },
			  toString: function() {//存在则最后调用
			    this.value++;
			    return this.value;
			  },
			  [Symbol.toPrimitive]() {//存在则优先调用
				this.value++;	
				return this.value;
			  }
			};
			console.log(a == 1 && a == 2 && a == 3) */			
			
			
			//请求的四部曲==============================
				// var request;
				// if(window.XMLHttpRequest){
				//   request=new XMLHttpRequest(); //IE7+,...
				// }else{
				//   request=new ActiveXObject("Microsoft.XMLHTTP");} //IE6,IE5
				// ---
				// request.open(method,url,async)//async为true的时候为异步
				// request.setRequestHeader("Content-type","application/x-www-form-urlencoded");  //post方法，而且必须写在open和send中间
				// ---
				// request.onreadystatechange = function() {
				// 	if(request.readyState == 4 &&request.status == 200) {
				// 		console.log(request.responseText);    
				// 	}
				// }
				// ---
				// request.send(参数||null)
			
			
			
			
			//滚动方向判断==============================
			// var a;			   
			// function scroll( fn ) {
			// 	var beforeScrollTop = document.body.scrollTop || document.documentElement.scrollTop,
			// 		fn = fn || function() {};
			// 	window.addEventListener("scroll", function() {
			// 		var afterScrollTop = document.body.scrollTop || document.documentElement.scrollTop,
			// 			delta = afterScrollTop - beforeScrollTop;
			// 		if( delta === 0 ) return false;
			// 		fn( delta > 0 ? "down" : "up" ,delta );
			// 		beforeScrollTop = afterScrollTop;
			// 	}, false);
			// }
			// scroll(function(direction,deltas) { 
			// 	// console.log(direction);
			// 	a =  direction;
			// }); 


			// 封装hook调用内容(可用于倒计时)==========================
			// function Timecout() {
			// 	this.nums = 0
			// }
			// Timecout.prototype.addnum = function(){
			// 	this.nums = this.nums + 2
			// }

			// var timecount = new Timecout()
			// var timecount2 = new Timecout()

			// timecount.addnum()
			// timecount.addnum()
			// console.log(timecount.nums)
			// timecount2.addnum()
			// console.log(timecount2.nums)
			
			
			
			//闭包======================================
			// function bibao(n){
			// 	var ms = n||5
			// 	return {
			// 		bibao:function(t){
			// 			console.log(t||ms)
			// 			return bibao(t)//形成了递归中的闭包
			// 		}
			// 	}
			// }
			// var a = bibao(6)
			// a.bibao(3)
			// a.bibao(4)
			// a.bibao(7)
			// a.bibao(6) 
			
			
			
			//关闭页面前弹出确认=========================
			//下面操作必须要操作页面才奏效
			/* window.onbeforeunload=function(){
				event.returnValue="请确定是否关闭或刷新当前页面？";
			} */
			
			
			
			//事件委托==================================
			// if(!Array.prototype.indexOf){
			// 	Array.prototype.indexOf = function(num){/* 全局处理这个，对低版本ie进行兼容 */
			// 		for(var i=0;i<this.length;i++){
			// 			if(this[i] == num){
			// 				return i;
			// 			}
			// 		}
			// 	}				
			// }
			// document.getElementById('wrap').addEventListener('click',function(events){
			// 	var eventss = events || window.event
			// 	eventss.stopPropagation()//阻止冒泡
			// 	eventss.preventDefault()//阻止默认事件
			// 	var target = eventss.target || eventss.srcElement
			// 	var zdy = Array.prototype.indexOf.call(document.querySelectorAll('.wrapitem'),target);
			// 	alert(zdy + '_' + target.className)
			//	如果需要获取下标，直接遍历，然后跟当前拿到的target直接对比，绝对等于，如果匹配就拿到下标
			// })
			/* jq以及zepto写法 */
			/* 
				$("#wrap").on("click",".wrapitem",function () {
					alert($(this).index());
				})
			 */
			
			
			
			//面向组合的例子=========================================
			//面向对象的一种优化
			/* function drive(){
			  console.log("wuwuwu!");
			}
			function music(){
			  console.log("lalala!")
			}
			function addOil(){
			  console.log("哦哟！")
			}
			
			let car = compose(drive, music, addOil);
			let newEnergyCar = compose(drive, music); */



			//图片懒加载============================================
			// var viewHeight = document.documentElement.clientHeight;

			// function lazyload() {
			// 	var imgs = document.querySelectorAll('img[data-original][lazyload]');
			// 	imgs.forEach(item => {

			// 		if (item.dataset.original == '') {
			// 			return;
			// 		}
			// 		var rect = item.getBoundingClientRect();
			// 		if (rect.bottom >= 0 && rect.top < viewHeight) {
			// 			var img = new Image();
			// 			img.src = item.dataset.original;
			// 			img.onload = function() {
			// 				item.src = img.src;
			// 			}
			// 			item.removeAttribute('data-original');
			// 			item.removeAttribute('lazyload')
			// 		}
			// 	})
			// }
			// lazyload();
			// document.addEventListener('scroll', lazyload)
			

			//解析url参数==================================================
			// function parseParam(url) {
			// const paramsStr = /.+\?(.+)$/.exec(url)[1];
			// const paramsArr = paramsStr.split('&');
			// let paramsObj = {};
			// paramsArr.forEach(param => {
			// 	if (/=/.test(param)) { // 处理有 value 的参数
			// 	let [key, val] = param.split('='); // 分割 key 和 value
			// 	val = decodeURIComponent(val); // 解码
			// 	val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字

			// 	if (paramsObj.hasOwnProperty(key)) { // 如果对象有 key，则添加一个值
			// 		paramsObj[key] = [].concat(paramsObj[key], val);
			// 	} else { // 如果对象没有这个 key，创建 key 并设置值
			// 		paramsObj[key] = val;
			// 	}
			// 	} else { // 处理没有 value 的参数
			// 	paramsObj[param] = true;
			// 	}
			// })

			// return paramsObj;
			// }
			// let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled';
			// parseParam(url)
			
			
			//es5构造函数===========================================
			/* -- 定义 -- */
			// var FnsEs5 = function(){
			// 	this.m = 3
			// }
			// FnsEs5.prototype.mv = 4
			// FnsEs5.prototype = {
			// 	get changemv() {
			// 		return this.mv
			// 	},
			// 	set changemv(value) {
			// 		//当触发就会响应这里的逻辑
			// 		this.mv = value
			// 	},
			// 	get changemv2() {
			// 		return this.mv
			// 	},
			// 	set changemv2(value) {
			// 		//当触发就会响应这里的逻辑
			// 		this.mv = value
			// 	}
			// }
			// /* FnsEs5.__proto__.__proto__.mv = 4 */
			// FnsEs5.prototype.fn = function(){
			// 	return this.mv
			// }
			// FnsEs5.ddss = 'xxx'//相当于class里面的static ddss = 'xxx'
			// var FnsEs5load = new FnsEs5()
			// FnsEs5load.fn.call({mv:9})/* call和apply可以把对象分配给某个构造函数使用，不同的时候，call第一个参数后面跟的是逐个传值，apply第一个参数后面跟的是数组集合传值 */
			// /* call和apply一经使用了之后，直接改变了当前方法的this指向，只指向于第一个参数传进去的对象或数组或fn */
			// /* -- 继承 -- */
			// var FnsEs52 = function(){}
			// FnsEs52.prototype.sv = 5
			// FnsEs52.prototype.objs = new FnsEs5()
			// var FnsEs52load = new FnsEs52()
			///* -- 优化版继承 -- */
			// var FnsEs52 = function(){}
			// FnsEs52.prototype = Object.create(FnsEs5.prototype)
			// FnsEs52.prototype.constructor = FnsEs52
			// var FnsEs52load = new FnsEs52()
			
			
			
			// //es6构造函数=============================================
			// /* -- 定义 -- */
			// class FnsEs6 {
			// 	constructor(test) {}
			// 	static sv = 3
			// 	static find = ()=>{
			// 		console.log(1111,this.sv)
			// 	}
			// 	m = 3
			// 	mv = 4
			// 	fns = function(){
			// 		return this.mv
			// 	}
			// 	get psv(){
			// 		return this.mv
			// 	}
			// 	set psv(value){
			// 		//当修改之后会触发
			// 		this.mv = value
			// 	}
			// 	get psv2(){
			// 		return this.mv
			// 	}
			// 	set psv2(value){
			// 		//当修改之后会触发
			// 		this.mv = value
			// 	}
			// }
			// var FnsEs6load = new FnsEs6('111')
			// /* -- 继承 -- */
			// class FnsEs62 extends FnsEs6 {
			// 	constructor(test,mst) {super(test);console.log(mst)}
			// }
			// var FnsEs62load = new FnsEs62('111','333')
			// /* static是直接类名调用，因为继承了上面的，所以可以直接拿到,static只能拿到当前class相关的static
			// 即static mv = 3可以被另外的static用方法进行this.mv获取到 */
			// FnsEs62.find()
			// /* get可以FnsEs62load.psv直接去拿返回的值，get和set必须是fn，而且必须要配套指针 */
			// console.log(FnsEs62load.psv)
			// FnsEs62load.psv = '3333vvvv'
			// FnsEs62load.psv2 = '33332vvvv'
			// console.log(FnsEs62load.psv,FnsEs62load.psv2)
			//
			//继承方式es5：1.直接call或者apply绑定进去，但无法完全继承进去
			//			  2.使用prototype属性，这种方式修改一个实例会影响另一个实例的对象参数
			//			  3.直接继承通过object。create创建的prototype对象
			//			  4.通过空函数进行中介继承，这种方式修改一个实例也会影响另一个实例的对象参数
			//			  5.拷贝继承
			

			
			//es6的async-await以及promise和promise.all===================
			/* async-await在不配合promise使用的时候，相当于同步 */
			// async function fnawait(){
			// 	var m = await (new Promise(function(r,f){
			// 		/* r是成功，反之失败，参数是自定义的 */
			// 		setTimeout(()=>{
			// 			r(1)
			// 			console.log(1)
			// 		},3000)
			// 	}));
			// 	//m有返回值下面才会执行,不管失败还是成功
			// 	console.log(2)
			// }
			// fnawait()
			
			
			/*promise链式，then里面返回promise，如果其中一个promise失败了，那么最后的catch就会返回对应的报错*/
			/* promise.all([p1,p2]).then((res)=>{}).catch((error)=>{}),有一个失败，就会打出对应子p的失败返回，常见使用场景 ： 多个异步结果合并到一起 */
			/* promise.race([p1,p2]).then((res)=>{}).catch((error)=>{}),只要有成功返回，就会打印最先执行完那个，不管失败与否，并且不会立刻停止，首个失败then将永远返回空，常见使用场景：把异步操作和定时器放到一起，如果定时器先触发，认为超时，告知用户 */
			/* 链式then：走完出来then回调里面又再return一个promise，并紧跟上一个then回调的后面在进行then回调 */
		</script>
	</body>
</html>
